#include<iostream>
#include<mysql/mysql.h>
#include<string>
#include<cstring>

//输出错误函数
void handleError(MYSQL* conn)
{
    std::cerr << "错误信息: " << mysql_error(conn) << std::endl;
    mysql_close(conn);
    exit(1);
}
//检查表是否存在
bool tableExists(MYSQL* conn,const std::string& tableName)
{
    MYSQL_RES* res;
    std::string query = "SHOW TABLES LIKE '" + tableName + "'";
    if(mysql_query(conn,query.data()))
    {
        handleError(conn);
    }
    res = mysql_store_result(conn);
    bool exist = (mysql_num_rows(res) > 0);
    mysql_free_result(res);
    return exist;
}
//创建user表
void createUsersTable(MYSQL* conn)
{
    const char* query = "create table users(id int auto_increment primary key,"
                                           "name varchar(50) not null,"
                                            "age int not null)";
    if(mysql_query(conn,query))
    {
        handleError(conn);
    }
}

//创建orders表
void createOrdersTable(MYSQL* conn)
{
    const char* query = "create table orders(id int auto_increment primary key,"
                                            " user_id int,"
                                            "order_date date,"
                                            " foreign key(user_id) references users(id))";
    if(mysql_query(conn,query))
    {
        handleError(conn);
    }
}

int main()
{
    //初始化MYSQL连接
    MYSQL* conn = mysql_init(nullptr);
    if(conn == nullptr)
    {
        std::cerr << "mysql_init()failed" << std::endl;
    }
    //连接服务器
    if(!mysql_real_connect(conn,"localhost","zt","zt921921","my_database",0,nullptr,CLIENT_MULTI_STATEMENTS))
    {
        handleError(conn);
    }
    if(mysql_autocommit(conn,0))
    {
        handleError(conn);
    }
    try
    {
        if(!tableExists(conn,"users"))
        {
            createUsersTable(conn);
        }
        if(!tableExists(conn,"orders"))
        {
            createOrdersTable(conn);
        }
        MYSQL_STMT* stmt = mysql_stmt_init(conn);
        if(stmt == nullptr)
        {
            handleError(conn);
        }
        const char* insertQuery = "insert into users(name,age) values(?,?)";
        if(mysql_stmt_prepare(stmt,insertQuery,std::strlen(insertQuery)))
        {
            handleError(conn);
        }
        MYSQL_BIND bind[2];
        std::memset(bind,0,sizeof(bind));
        char name[20] = "John Doe";
        bind[0].buffer_type = MYSQL_TYPE_STRING;
        bind[0].buffer = name;
        bind[0].buffer_length = std::strlen(name);

        int age = 20;
        bind[1].buffer_type = MYSQL_TYPE_LONG;
        bind[1].buffer = &age;
        
        if(mysql_stmt_bind_param(stmt,bind))
        {
            handleError(conn);
        }
        if(mysql_stmt_execute(stmt))
        {
            handleError(conn);
        }
        mysql_stmt_close(stmt);

        const char* multiQuery = "select * from users;select * from orders";
        if(mysql_query(conn,multiQuery))
        {
            handleError(conn);
        }
        MYSQL_RES* result;
        do
        {
            result = mysql_store_result(conn);
            if(result)
            {
                std::cout << "Result set:" << std::endl;
            }
            MYSQL_ROW row;
            while((row = mysql_fetch_row(result)))
            {
                for(int i = 0;i < mysql_num_fields(result);++i)
                {
                    std::cout << (row[i]?row[i]:"nullptr") << " " << std::endl;
                }
                std::cout << std::endl;
            }
            mysql_free_result(result);
        }while(mysql_next_result(conn) == 0);
    if(mysql_commit(conn))
    {
        handleError(conn);
    }
}
catch(...)
{
    if(mysql_rollback(conn))
    {
        handleError(conn);
    }
}
    mysql_close(conn);

    return 0;
}